package com.bosicloud.cmb.ibp.api.manager.controller;

import com.bosicloud.cmb.ibp.api.manager.commom.constant.ResultConstant;
import com.bosicloud.cmb.ibp.api.manager.commom.constant.UrlDefine;
import com.bosicloud.cmb.ibp.api.manager.commom.model.*;
import com.bosicloud.cmb.ibp.api.manager.commom.vo.*;
import com.bosicloud.cmb.ibp.api.manager.service.ApimgmtService;
import com.bosicloud.cmb.ibp.commom.dto.Pagination;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author Jack Peng / ziliang.peng@bosicloud.com
 */
@Slf4j
@RestController
@Api(value = "API管理控制器", description = "API管理")
public class ApimgmtController {

    @Autowired
    ApimgmtService apimgmtService;

    @GetMapping(UrlDefine.ALL_CATEGORY)
    public Object allCategory() {
        return apimgmtService.allCategory();
    }

    @ApiOperation(value = "分页获取API")
    @HystrixCommand
    @GetMapping(UrlDefine.API_PAGE + "/{currentPage}/{pageSize}")
    public Pagination<IbpApi> pagingApi(@PathVariable(value = "currentPage") Integer currentPage,
                                        @PathVariable(value = "pageSize") Integer pageSize,
                                        @RequestParam(required = false, value = "categoryId") Integer categoryId) {
        return apimgmtService.pagingApi(currentPage, pageSize, Optional.ofNullable(categoryId));
    }

    @ApiOperation(value = "API市场查询")
    @HystrixCommand
    @GetMapping(value = UrlDefine.SEARCH_API + "/{currentPage}/{pageSize}")
    public Pagination<IbpApiVO> searchApi(@PathVariable(value = "currentPage") Integer currentPage,
                                          @PathVariable(value = "pageSize") Integer pageSize,
                                          @RequestParam(required = false, value = "categoryId") Integer categoryId,
                                          @RequestParam(required = false, value = "searchText") String searchText) {

        return apimgmtService.searchApi(currentPage, pageSize, Optional.ofNullable(categoryId),
                Optional.ofNullable(searchText));
    }


    @ApiOperation(value = "API详情")
    @HystrixCommand
    @GetMapping(UrlDefine.API_DETAIL + "/{apiId}")
    public IbpApiVO searchApiDetail(@PathVariable(value = "apiId") Integer apiId) {
        return apimgmtService.searchApiDetailById(apiId);
    }

    @ApiOperation(value = "根据apiId获取Api方法列表")
    @HystrixCommand
    @GetMapping(UrlDefine.METHOD_LIST + "/{apiId}")
    public List<ApiMethodListVO> searchApiMethodListByApiId(@PathVariable(value = "apiId") Integer apiId) {
        return apimgmtService.searchApiMethodListByApiId(apiId);
    }

    @ApiOperation(value = "根据docsId查询方法详情")
    @HystrixCommand
    @GetMapping(UrlDefine.METHOD_INFO + "/{docsId}")
    public MethodInfoVO searchApiMethodInfoByDocsId(@PathVariable(value = "docsId") Integer docsId) {
        return apimgmtService.searchApiMethodInfoByDocsId(docsId);
    }

    @ApiOperation(value = "添加API")
    @HystrixCommand
    @PostMapping(UrlDefine.ADD_API)
    public String addApi(@RequestBody @Valid IbpApi ibpApi) {
        return apimgmtService.performAddApiLogic(ibpApi);
    }

    @ApiOperation(value = "根据apiId查詢ApiDocs列表")
    @HystrixCommand
    @GetMapping(UrlDefine.API_DOCS_LIST + "/{apiId}")
    public List<IbpApiDocs> searchApiDocsListByApiId(@PathVariable(value = "apiId") Integer apiId) {
        return apimgmtService.searchApiDocsListByApiId(apiId);
    }

    @ApiOperation(value = "更新API 参数示例等文档信息")
    @HystrixCommand
    @PutMapping(UrlDefine.METHOD_INFO)
    public String updateApiMethodInfo(@RequestBody MethodInfoVO methodInfoVO) {
        int updateCount = 0;
        try {
            updateCount = apimgmtService.updateApiMethodInfo(methodInfoVO);
        } catch (Exception e) {
            log.error("update method info exception:{}", e.getMessage(), e);
        }
        return updateCount > 0 ? ResultConstant.SUCCESS : ResultConstant.FAILURE;

    }

    @ApiOperation(value = "部署API")
    @HystrixCommand
    @PostMapping(value = UrlDefine.DEPLOY_API, produces = MediaType.APPLICATION_JSON_VALUE)
    public String deployApi(@RequestBody @Valid DeployApiParamVO deployApiParamVO) {
        return apimgmtService.deployApi(deployApiParamVO);

    }

    @ApiOperation(value = "Api开发者列表", response = Pagination.class)
    @HystrixCommand
    @GetMapping(value = UrlDefine.API_LIST + "/{currentPage}/{pageSize}/users/{userId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Pagination<IbpApiVO> searchApiDeveloperList(@ApiParam(name = "currentPage", value = "当前页数", required = true)
                                                       @PathVariable(value = "currentPage") Integer currentPage,
                                                       @ApiParam(name = "pageSize", value = "每页显示条数", required = true)
                                                       @PathVariable(value = "pageSize") Integer pageSize,
                                                       @ApiParam(name = "userId", value = "登录用户ID", required = true)
                                                       @PathVariable(value = "userId") Integer userId) {
        return apimgmtService.searchApiDeveloperList(currentPage, pageSize, userId);
    }


    @ApiOperation(value = "订阅API")
    @HystrixCommand
    @PostMapping(value = UrlDefine.SUBSCRIBE_API)
    public String subscribeApi(@RequestBody @Valid SubscribeApiParamVO subscribeApiParamVO) {
        return apimgmtService.subscribeApi(subscribeApiParamVO);

    }

    @ApiOperation(value = "取消订阅")
    @HystrixCommand
    @PostMapping(value = UrlDefine.UNSUBSCRIBE_API)
    public String unSubscribeApi(@RequestBody @Valid SubscribeApiParamVO subscribeApiParamVO) {
        return apimgmtService.unSubscribeApi(subscribeApiParamVO);

    }

    @ApiOperation(value = "删除API")
    @HystrixCommand
    @DeleteMapping(value = UrlDefine.DELETE_API)
    public String deleteApi(@RequestBody @Valid DeleteApiParamVO deleteApiParamVO) {
        return apimgmtService.deleteApi(deleteApiParamVO);

    }


    @ApiOperation(value = "订阅列表", response = Pagination.class)
    @HystrixCommand
    @GetMapping(value = UrlDefine.SUBSCRIBE_API_LIST + "/{currentPage}/{pageSize}/users/{userId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Pagination<SubscribeApiListVO> subscribeApiList(@ApiParam(name = "currentPage", value = "当前页数", required = true)
                                                           @PathVariable(value = "currentPage") Integer currentPage,
                                                           @ApiParam(name = "pageSize", value = "每页显示条数", required = true)
                                                           @PathVariable(value = "pageSize") Integer pageSize,
                                                           @ApiParam(name = "userId", value = "登录用户ID", required = true)
                                                           @PathVariable(value = "userId") Integer userId) {
        return apimgmtService.subscribeApiList(currentPage, pageSize, userId);
    }

    @ApiOperation(value = "检查是否可以订阅", response = Pagination.class)
    @HystrixCommand
    @GetMapping(value = UrlDefine.CHECK_SUBSCRIBE_AVAILABLE + "/{apiId}/users/{userId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Boolean checkSubscribeIsAvailable(@ApiParam(name = "apiId", value = "apiId", required = true)
                                             @PathVariable(value = "apiId") Integer apiId,
                                             @ApiParam(name = "userId", value = "登录用户ID", required = true)
                                             @PathVariable(value = "userId") Integer userId) {
        return apimgmtService.checkSubscribeIsAvailable(apiId, userId);
    }

    @ApiOperation(value = "获取发布失败信息", response = IbpApiAwsFailtMsg.class)
    @HystrixCommand
    @GetMapping(value = UrlDefine.DEPLOY_FAIL_MSG + "/{apiId}/{bizType}", produces = MediaType.APPLICATION_JSON_VALUE)
    public IbpApiAwsFailtMsg searchFailMsg(@ApiParam(name = "apiId", value = "apiId", required = true)
                                           @PathVariable(value = "apiId") Integer apiId,
                                           @ApiParam(name = "bizType",
                                                   value = "业务类型[CREATE_API,CREATE_KEY,DEPLOY_KEY,SUBSCRIBE_KEY," +
                                                           "UN_SUBSCRIBE_KEY,DELETE_API_KEY]", required = true)
                                           @PathVariable(value = "bizType") String bizType,
                                           @ApiParam(name = "context", value = "环境/上下文")
                                           @RequestParam(value = "context", required = false) String context) {
        return apimgmtService.searchFailMsg(apiId, bizType, context);
    }

    @ApiOperation(value = "是否公共API", response = String.class)
    @HystrixCommand
    @PutMapping(value = UrlDefine.PUBLIC_API + "/{apiId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public String isPublicAPi(@ApiParam(name = "apiId", value = "apiId", required = true)
                              @PathVariable(value = "apiId") Integer apiId) {
        return apimgmtService.isPublicApi(apiId);
    }

    @ApiOperation(value = "查询UsagePlan列表", response = List.class)
    @HystrixCommand
    @GetMapping(value = UrlDefine.USAGE_PLAN_LIST + "/{apiId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public List<IbpApiUsagePlan> searchUsagePlanList(@ApiParam(name = "apiId", value = "apiId", required = true)
                                                     @PathVariable(value = "apiId") Integer apiId) {
        return apimgmtService.searchUsagePlanListByApiId(apiId);
    }

    @ApiOperation(value = "查询当前apiName是否存在", response = Boolean.class)
    @HystrixCommand
    @GetMapping(value = UrlDefine.CHECK_API_NAME + "/{apiName}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Boolean checkApiName(@ApiParam(name = "apiName", value = "apiName", required = true)
                                @PathVariable(value = "apiName") String apiName) {
        List<IbpApi> apiList = apimgmtService.searchApiListFor(IbpApi.builder().apiName(apiName).build());
        return CollectionUtils.isNotEmpty(apiList);
    }

    @ApiOperation(value = "根据apiId/用户ID查询订阅API信息")
    @HystrixCommand
    @GetMapping(value = UrlDefine.SEARCH_SUBSCRIBE_INFO + "/{userId}/{apiId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public IbpUserConsumerApi searchUserConsumerApi(@ApiParam(name = "apiId", value = "apiId", required = true)
                                                    @PathVariable(value = "apiId") Integer apiId,
                                                    @ApiParam(name = "userId", value = "用户登录ID", required = true)
                                                    @PathVariable(value = "userId") Integer userId) {
        return apimgmtService.searchIbpUserConsumerApi(apiId, userId);
    }

    @ApiOperation(value = "根据docsId查询Response列表")
    @HystrixCommand
    @GetMapping(value = UrlDefine.RESPONSE_CODE_LIST + "/{docsId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public List<IbpApiDocResponseMgs> searchApiDocResponseMgsByDocsId(@PathVariable(value = "docsId") Integer docsId) {
        return apimgmtService.searchApiDocResponseMgsByDocsId(docsId);
    }

    @ApiOperation(value = "根据responseMsgId查询Response model/headers")
    @HystrixCommand
    @GetMapping(value = UrlDefine.RESPONSE_MODEL_HEADERS + "/{responseMsgId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Map<String, Object> searchResponseModelAndHeadersById(@PathVariable(value = "responseMsgId") Integer responseMsgId) {
        Map<String, Object> map = new HashMap<>();
        map.put("responseModel", Optional.ofNullable(apimgmtService.searchApiDocResponseMgsById(responseMsgId))
                .map(IbpApiDocResponseMgs::getResponseModel)
                .orElse("{}"));
        map.put("headers", apimgmtService.searchApiDocResponseHeadersByResponseMsgId(responseMsgId));
        return map;
    }

}
